#include "udpcom.h"

#include "icom.h"

#include <Qt>
#include <QObject>
#include <QUdpSocket>
#include <QSemaphore>
#include <QThread>
#include <QNetworkDatagram>

UdpCom::UdpCom()
{
	m_address = m_cDefaultAddress;
	m_port = m_cDefaultPort;

	m_sem = new QSemaphore(0);

	m_thread_running = false;
	m_thread = new QThread();
	m_socket = new QUdpSocket(m_thread);

	moveToThread(m_thread);

	// 绑定线程循环体
	connect(m_thread, SIGNAL(started()), this, SLOT(Udp_ReadyRead()));
}

bool UdpCom::IsConnected()
{
	if (!m_socket)
	{
		if (m_socket->isOpen())
		{
			return true;
		}
	}
	return false;
}

bool UdpCom::Connect(char *pAddr, char *pPort)
{
	QHostAddress address = QHostAddress(m_address);
	quint16 port = m_port.toUShort();
	// address
	if (pAddr != nullptr)
	{
		address = QHostAddress(QString(pAddr));
		m_address = QString(pAddr);
	}

	// port
	if (pPort != nullptr)
	{
		const int portx = QString(pPort).toUShort();
		if (portx != -1)
		{
			port = portx;
			m_port = &""[port];
		}
	}

	if (m_socket->bind(address, port))
	{
		m_thread_running = true;
		m_thread->start();
		return true;
	}
	else
	{
		return false;
	}
}

bool UdpCom::Disconnect()
{
	if (m_thread != nullptr)
	{
		m_thread_running = false;
		m_thread->quit();
		m_thread->wait();
	}
	if (m_socket != nullptr)
	{
		m_socket->close();
	}
	return true;
}

int UdpCom::GetChar(int timeout)
{
	return 0;
}

int UdpCom::GetPacket(ComMessage &message, int timeout)
{
	if (timeout == -1) {
		timeout = this->timeout;
	}

	if (m_sem->tryAcquire(1, timeout))
	{
		message = m_message;
		qDebug() << "UdpCom::GetPacket() recv data!";
		return 0;
	}
	else
	{
		qDebug() << "UdpCom::GetPacket() recv timeout!";
		return -1;
	}
}

void UdpCom::PutChar(char c)
{

}

void UdpCom::PutPacket(ComMessage &message)
{
	QStringList target = message.m_target.split('.');
	if (target.size() == 3 && target[0] == "UDP")
	{
		const QHostAddress address(target[1]);
		const quint16 port = target[2].toUShort();
		m_socket->writeDatagram(message.data(), message.size(), address, port);
	}
}

void UdpCom::Udp_ReadyRead()
{
	QHostAddress address;
	quint16 port;
	while (true) {
		if (m_socket != nullptr && m_thread_running)
		{
			while (m_socket->hasPendingDatagrams())
			{
				m_message.resize(m_socket->pendingDatagramSize());
				m_socket->readDatagram(m_message.data(), m_message.size(), &address, &port);
				m_message.m_target = "UDP." + address.toString() + "." + QString::number(port);
				if (0 == m_sem->available())
				{
					m_sem->release();
				}
				else
				{
					qDebug() << "E> UdpCom::Udp_ReadyRead() sem not zero!";
				}
			}
		}
		else
		{
			return;
		}
		QThread::msleep(1);
	}
}
